The following is a tutorial for the 2022 LTER All Scientists’ Meeting pulse dynamics workshop about the basic use of the WaveletComp R package for wavelet and cross-wavelet analysis of time series data of one and two variables, respectively.
For a thorough discussion of WaveletComp, refer to the excellent guided tour document that accompanies the package. The guided tour goes into much greater detail than this tutorial, and much of this tutorial’s materials are based on the guided tour.
A simple, template R script is also available along with this tutorial - see LTER_Pulses_WaveletComp_template.R.
Wavelets provide a method for studying periodic time series phenomena that may be either stationary or non-stationary over time. This allows for the examination of time series data in both the time and frequency domains.
A wavelet function, the “mother” wavelet, is scaled (stretched and compressed) into a series of wavelet children. The children are shifted/translated across the entire time series. This is called a convolution of the time series with the wavelet children and is the wavelet transform.
There are many types of wavelets and WaveletComp uses the Morlet wavelet:
The wavelet analysis provides the wavelet power spectrum that can be interpreted as time-frequency wavelet energy density, and is related to the amplitude of a periodic signal at a given point in time.
The relationship between period and frequency is:
Period = 1 / Frequency
There is a trade off between time and frequency resolution. Long periods are well detected in the frequency domain, but poorly localized in the time domain. Short periods are well detected in the time domain, but poorly localized in the frequency domain.
Through the wavelet transform, it is possible to identify what periodicities are most strongly present in a univariate time series.
By utilizing a series of simulations, WaveletComp tests the null hypothesis of no periodicity using a white noise process or several other test options. Regions of the time series that are significantly different from the null may be identified in the model output and visualizations.
Cross-wavelet analysis allows for comparison of the frequency contents of a bivariate time series, thus allowing for an examination of synchronicity or coherency between the two time series. Coherency is analogous to classical correlation. The cross-wavelet power shows the similarity of the bivariate time series’ wavelet power in the time-frequency domain. It also allows for the assessment of how closely in/out of phase the two time series are.
Some examples will help to provide a better understanding of the wavelet transform of time series data.
One synthetic data example is provided that is directly from the guided tour.
The other data used in the examples below are daily AmeriFlux data from the US-Seg: Sevilleta grassland flux tower located on the Sevilleta National Wildlife Refuge in New Mexico from 2007-2020. Latitude/Longitude: 34.3623, -106.7020. Elevation: 1596 m. See the AmeriFlux site info page for more information. Variables from the data that are used in the tutorial include daily mean air temperature, precipitation, and net ecosystem exchange (NEE).
Utilize wavelets to conduct cross-site comparisons of pulse dynamics within (and beyond) the LTER Network.
Motivating questions include:
Several R packages are loaded along with the daily US-Seg data.
library(WaveletComp)
library(dplyr)
library(matrixStats)
library(tidyr)
library(ggplot2)
library(lubridate)
library(readr)
seg <- read_csv("~/Documents/LTER_Pulse_Time_Series_WG/SEV_daily_flux/US-Seg_daily_aflx.csv") %>%
mutate(date = mdy(Date)) %>% # WaveletComp expects date var named "date"
select(-Date) %>%
select(date, everything()) %>%
arrange(date) # make sure data are properly sorted in chronological order
## Rows: 5114 Columns: 23
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Date
## dbl (22): GPP_int, GPP_dayint, RECO_int, RECO_dayint, RECO_nightint, NEE_int...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Let’s take a quick look at the data we are working with.
Data structure:
str(seg)
## tibble [5,114 × 23] (S3: tbl_df/tbl/data.frame)
## $ date : Date[1:5114], format: "2007-01-01" "2007-01-02" ...
## $ GPP_int : num [1:5114] 0 0.00395 0.0362 0.25915 0.46783 ...
## $ GPP_dayint : num [1:5114] 0 0.00228 0.0362 0.13995 0.24107 ...
## $ RECO_int : num [1:5114] 0.495 0.61 0.7 0.592 0.514 ...
## $ RECO_dayint : num [1:5114] 0.247 0.262 0.234 0.273 0.268 ...
## $ RECO_nightint: num [1:5114] 0.249 0.348 0.465 0.32 0.246 ...
## $ NEE_int : num [1:5114] 0.495 0.606 0.664 0.333 0.046 ...
## $ NEE_dayint : num [1:5114] 0.2467 0.2594 0.1982 0.1328 0.0272 ...
## $ NEE_nightint : num [1:5114] 0.2486 0.3464 0.4654 0.2005 0.0188 ...
## $ ET_int : num [1:5114] 0.368 0.25 0.255 0.458 0.864 ...
## $ ET_dayint : num [1:5114] 0.359 0.262 0.305 0.425 0.794 ...
## $ P_int : num [1:5114] 0.614 1.024 0 0 1.024 ...
## $ TA_avg : num [1:5114] -8.53 -5.98 -7.56 -1.98 3.52 ...
## $ TA_max : num [1:5114] -2.14 -3.26 -2.93 6.94 9.91 ...
## $ RH_avg : num [1:5114] 88.5 86.5 87.9 72.6 63.1 ...
## $ SW_IN_avg : num [1:5114] 125 128 145 150 150 ...
## $ NETRAD_avg : num [1:5114] -34.28 -33.93 -8.28 -7.74 3.35 ...
## $ PPFD_IN_avg : num [1:5114] 243 249 282 291 291 ...
## $ PPFD_IN_sum : num [1:5114] 11407 11948 13517 13951 13985 ...
## $ VPD_avg : num [1:5114] 0.0375 0.0569 0.0477 0.1822 0.3185 ...
## $ VPD_max : num [1:5114] 0.226 0.267 0.174 0.543 0.774 ...
## $ LE_avg : num [1:5114] 13.28 8.77 9.01 15.69 28.8 ...
## $ H_avg : num [1:5114] 15.94 7 10.08 2.15 -6.45 ...
Data summary:
summary(seg)
## date GPP_int GPP_dayint RECO_int
## Min. :2007-01-01 Min. :0.0000 Min. :0.00000 Min. :0.001662
## 1st Qu.:2010-07-02 1st Qu.:0.1340 1st Qu.:0.09379 1st Qu.:0.195740
## Median :2013-12-31 Median :0.2662 Median :0.22001 Median :0.345905
## Mean :2013-12-31 Mean :0.5864 Mean :0.53488 Mean :0.521193
## 3rd Qu.:2017-07-01 3rd Qu.:0.7426 3rd Qu.:0.68267 3rd Qu.:0.658740
## Max. :2020-12-31 Max. :5.2217 Max. :5.10939 Max. :5.882377
##
## RECO_dayint RECO_nightint NEE_int NEE_dayint
## Min. :0.0000 Min. :0.00000 Min. :-3.008381 Min. :-3.78218
## 1st Qu.:0.1021 1st Qu.:0.07787 1st Qu.:-0.195228 1st Qu.:-0.34236
## Median :0.1836 Median :0.15992 Median :-0.006409 Median :-0.07767
## Mean :0.2997 Mean :0.22151 Mean :-0.065162 Mean :-0.23520
## 3rd Qu.:0.3883 3rd Qu.:0.27416 3rd Qu.: 0.141722 3rd Qu.: 0.04146
## Max. :4.3728 Max. :1.60844 Max. : 5.810892 Max. : 4.31067
##
## NEE_nightint ET_int ET_dayint P_int
## Min. :-0.85730 Min. :0.01599 Min. :0.0000 Min. : 0.0000
## 1st Qu.: 0.03406 1st Qu.:0.19703 1st Qu.:0.1950 1st Qu.: 0.0000
## Median : 0.11403 Median :0.38021 Median :0.3622 Median : 0.0000
## Mean : 0.17004 Mean :0.58996 Mean :0.5605 Mean : 0.6319
## 3rd Qu.: 0.22711 3rd Qu.:0.75909 3rd Qu.:0.7085 3rd Qu.: 0.0000
## Max. : 1.56843 Max. :4.26213 Max. :4.2112 Max. :46.3441
##
## TA_avg TA_max RH_avg SW_IN_avg
## Min. :-18.914 Min. :-16.44 Min. : 6.062 Min. : 9.236
## 1st Qu.: 6.075 1st Qu.: 13.47 1st Qu.:26.113 1st Qu.:163.145
## Median : 14.267 Median : 21.77 Median :38.656 Median :235.172
## Mean : 13.712 Mean : 20.88 Mean :40.155 Mean :231.808
## 3rd Qu.: 21.993 3rd Qu.: 28.99 3rd Qu.:52.572 3rd Qu.:300.307
## Max. : 30.313 Max. : 38.58 Max. :98.833 Max. :385.824
##
## NETRAD_avg PPFD_IN_avg PPFD_IN_sum VPD_avg
## Min. :-86.76 Min. : 0.0535 Min. : 0 Min. :0.006617
## 1st Qu.: 40.06 1st Qu.: 303.3559 1st Qu.:14138 1st Qu.:0.554238
## Median : 77.19 Median : 442.0772 Median :20836 Median :1.106678
## Mean : 77.84 Mean : 438.4796 Mean :20492 Mean :1.272664
## 3rd Qu.:112.63 3rd Qu.: 576.5788 3rd Qu.:27422 3rd Qu.:1.830674
## Max. :654.11 Max. :1977.1261 Max. :34865 Max. :4.143947
## NA's :195 NA's :100
## VPD_max LE_avg H_avg
## Min. :0.01723 Min. : 0.5317 Min. :-30.02
## 1st Qu.:1.18398 1st Qu.: 6.3996 1st Qu.: 30.39
## Median :2.16125 Median : 12.0348 Median : 50.88
## Mean :2.33556 Mean : 18.5688 Mean : 52.94
## 3rd Qu.:3.34840 3rd Qu.: 23.8515 3rd Qu.: 74.22
## Max. :6.43246 Max. :134.6514 Max. :143.23
##
Notice that there are no missing data. WaveletComp requires a complete time series without missing data. It may be necessary for you to preprocess your data to gap fill any missing data.
Data head:
head(seg, 10)
## # A tibble: 10 × 23
## date GPP_int GPP_dayint RECO_int RECO_dayint RECO_nightint NEE_int
## <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2007-01-01 0 0 0.495 0.247 0.249 0.495
## 2 2007-01-02 0.00395 0.00228 0.610 0.262 0.348 0.606
## 3 2007-01-03 0.0362 0.0362 0.700 0.234 0.465 0.664
## 4 2007-01-04 0.259 0.140 0.592 0.273 0.320 0.333
## 5 2007-01-05 0.468 0.241 0.514 0.268 0.246 0.0460
## 6 2007-01-06 0.0969 0.0526 0.374 0.184 0.190 0.277
## 7 2007-01-07 0.115 0.113 0.448 0.189 0.259 0.333
## 8 2007-01-08 0.118 0.104 0.373 0.145 0.228 0.255
## 9 2007-01-09 0.129 0.108 0.314 0.117 0.197 0.185
## 10 2007-01-10 0.196 0.123 0.290 0.146 0.144 0.0938
## # … with 16 more variables: NEE_dayint <dbl>, NEE_nightint <dbl>, ET_int <dbl>,
## # ET_dayint <dbl>, P_int <dbl>, TA_avg <dbl>, TA_max <dbl>, RH_avg <dbl>,
## # SW_IN_avg <dbl>, NETRAD_avg <dbl>, PPFD_IN_avg <dbl>, PPFD_IN_sum <dbl>,
## # VPD_avg <dbl>, VPD_max <dbl>, LE_avg <dbl>, H_avg <dbl>
This first example examines the underlying periodic structures of US-Seg mean daily temperature in Celsius. The example exhibits simple periodic structure, but it is a useful introduction to wavelets.
The US-Seg Average Daily Temperature time series:
seg %>%
ggplot(aes(x = date, y = TA_avg)) +
geom_line(size = 0.4, color = "tan") +
labs(title = "US-Seg - Average Daily Temperature\n2007-2020",
x = "Date",
y = "Average Temperature (C)")
The analyze.wavelet function performs the wavelet
transformation and provides the power spectrum for mean daily
temperature for the time series:
seg_ta_avg.w <- analyze.wavelet(seg, "TA_avg",
loess.span = 0.75,
dt = 1, dj = 1/20,
make.pval = TRUE, method = "white.noise",
n.sim = 25) # should set n.sim higher - default is 100
## Smoothing the time series...
## Starting wavelet transformation...
## ... and simulations...
##
|
| | 0%
|
|=== | 4%
|
|====== | 8%
|
|======== | 12%
|
|=========== | 16%
|
|============== | 20%
|
|================= | 24%
|
|==================== | 28%
|
|====================== | 32%
|
|========================= | 36%
|
|============================ | 40%
|
|=============================== | 44%
|
|================================== | 48%
|
|==================================== | 52%
|
|======================================= | 56%
|
|========================================== | 60%
|
|============================================= | 64%
|
|================================================ | 68%
|
|================================================== | 72%
|
|===================================================== | 76%
|
|======================================================== | 80%
|
|=========================================================== | 84%
|
|============================================================== | 88%
|
|================================================================ | 92%
|
|=================================================================== | 96%
|
|======================================================================| 100%
## Class attributes are accessible through following names:
## series loess.span dt dj Wave Phase Ampl Power Power.avg Power.pval Power.avg.pval Ridge Period Scale nc nr coi.1 coi.2 axis.1 axis.2 date.format date.tz
analyze.wavelet has numerous arguments that you can set
and tweak from their defaults, so check out the documentation for the
function using ?analyze.wavelet in the R console.
What do you think the most powerful period(s) will be for the average daily temperature time series?
# you can define your continuous color palette
# mypalette <- "terrain.colors(100)"
wt.image(seg_ta_avg.w,
col.contour = "white",
# color.palette = mypalette,
lwd = 1.5,
show.date = TRUE,
main = "US-Seg Flux Tower Daily Mean Air Temperature (C)",
legend.params = list(width = 1.8, label.digits = 4, lab = "Power"))
The most powerful periods in the time series are around the annual temperature cycle of ~365 days. However, if you look closely, there are a couple of other periods with high power at certain time ranges in the time series.
The average power of the entire time series can be graphed:
# look at the average power of the series
maximum.level = 1.001*max(seg_ta_avg.w$Power.avg) # See WaveletComp Guided Tour for explanation
wt.avg(seg_ta_avg.w, maximum.level = maximum.level,
legend.coords = "bottomright",
main = "Average Power for US-Seg Mean Daily Air Temperature")
Because the wavelet transform preserves information, it is possible to reconstruct the original time series for the time periods whose average power were found to be significantly different from a white noise structure:
reconstruct(seg_ta_avg.w,
show.date = TRUE,
legend.coords = "bottomright",
ylim = c(-40, 20),
main = "Reconstruction of US-Seg Flux Tower \nDaily Mean Airt Temperature",
col = c('tan', 'black'))
## Your input object class is 'analyze.wavelet'...
## Your time series 'TA_avg' will be reconstructed...
## Starting the reconstruction process...
## Original (detrended) and reconstructed series are being plotted...
## Class attributes are accessible through following names:
## series rec.waves loess.span lvl only.coi only.sig siglvl only.ridge rnum.used rescale dt dj Period Scale nc nr axis.1 axis.2 date.format date.tz
analyze.wavelet produces several results variables that
can be used for further analysis. After inspecting the wavelet image, it
may be interesting to look more closely at powerful periods in certain
time ranges. The period information output from
analyze.wavelet may be used to pinpoint and examine
periodicities of interest:
seg_ta_avg.w$Period
## [1] 2.000000 2.070530 2.143547 2.219139 2.297397 2.378414
## [7] 2.462289 2.549121 2.639016 2.732081 2.828427 2.928171
## [13] 3.031433 3.138336 3.249010 3.363586 3.482202 3.605002
## [19] 3.732132 3.863745 4.000000 4.141060 4.287094 4.438278
## [25] 4.594793 4.756828 4.924578 5.098243 5.278032 5.464161
## [31] 5.656854 5.856343 6.062866 6.276673 6.498019 6.727171
## [37] 6.964405 7.210004 7.464264 7.727491 8.000000 8.282119
## [43] 8.574188 8.876556 9.189587 9.513657 9.849155 10.196485
## [49] 10.556063 10.928322 11.313708 11.712686 12.125733 12.553346
## [55] 12.996038 13.454343 13.928809 14.420007 14.928528 15.454981
## [61] 16.000000 16.564239 17.148375 17.753112 18.379174 19.027314
## [67] 19.698311 20.392970 21.112127 21.856644 22.627417 23.425371
## [73] 24.251465 25.106691 25.992077 26.908685 27.857618 28.840015
## [79] 29.857056 30.909963 32.000000 33.128478 34.296751 35.506223
## [85] 36.758347 38.054628 39.396621 40.785940 42.224253 43.713288
## [91] 45.254834 46.850742 48.502930 50.213382 51.984153 53.817371
## [97] 55.715236 57.680030 59.714111 61.819925 64.000000 66.256955
## [103] 68.593502 71.012446 73.516695 76.109255 78.793242 81.571880
## [109] 84.448506 87.426576 90.509668 93.701485 97.005860 100.426765
## [115] 103.968307 107.634741 111.430472 115.360059 119.428223 123.639850
## [121] 128.000000 132.513910 137.187003 142.024892 147.033389 152.218511
## [127] 157.586485 163.143760 168.897013 174.853153 181.019336 187.402969
## [133] 194.011721 200.853529 207.936613 215.269482 222.860944 230.720118
## [139] 238.856446 247.279700 256.000000 265.027821 274.374006 284.049785
## [145] 294.066779 304.437021 315.172970 326.287521 337.794025 349.706306
## [151] 362.038672 374.805938 388.023441 401.707058 415.873227 430.538965
## [157] 445.721888 461.440237 477.712892 494.559400 512.000000 530.055641
## [163] 548.748013 568.099570 588.133558 608.874043 630.345940 652.575041
## [169] 675.588050 699.412611 724.077344 749.611876 776.046882 803.414116
## [175] 831.746454 861.077929 891.443777 922.880474 955.425783 989.118801
## [181] 1024.000000 1060.111282 1097.496026 1136.199139 1176.267116 1217.748086
## [187] 1260.691879 1305.150082 1351.176101 1398.825223 1448.154688 1499.223753
## [193] 1552.093764 1606.828232 1663.492908
Let’s look at the power of the periods around 365. The 365-day period is between records 151 and 152. The following looks at a broad range of periods between 256 and 512 days.
Convert power data to a matrix:
seg_ta_avg.w_power <- as.matrix(seg_ta_avg.w$Power)
The dimensions of the Power matrix have the number of periods as columns and the number of records in the time series as rows:
dim(seg_ta_avg.w$Power)
## [1] 195 5114
From this, it is possible to pull out various results from
analyze.wavelet. For example, here are the results looking
at the periodicities from 256 to 512:
seg_256_to_512_power <- as.matrix(seg_ta_avg.w_power[141:161,])
dimnames(seg_256_to_512_power) <- list(paste0("period_", round(seg_ta_avg.w$Period[141:161], 2)))
seg_256_to_512_power_t <- as_tibble(t(seg_256_to_512_power))
seg_256_to_512_power_df <- tibble(date = seg$date, seg_256_to_512_power_t)
seg_256_to_512_power_df_long <- seg_256_to_512_power_df %>%
pivot_longer(contains("period_"))
seg_256_to_512_power_df_long %>%
ggplot(aes(x = date, y = value, color = name)) +
geom_line() +
facet_wrap(~ name) +
theme(legend.position="none") +
labs(title = "Average daily temperature periods around 365",
x = "Date",
y = "Power")
Looking closely at the wavelet image, there appears to be some high power periods in 2011 between 20 and 50 day periods:
This is the time series for 2011:
seg %>%
filter(year(date) == 2011) %>%
ggplot(aes(x = date, y = TA_avg)) +
geom_line(size = 0.6) +
labs(title = "2011 Daily Average Temperature (C)")
There was a strong freeze in February 2011, and this shows up in the wavelet transform.
To pull out the 2011 data from analyze.wavelet, identify
the 2011 records:
(start_2011 <- ymd("2011-01-01") - ymd(min(seg$date)))
## Time difference of 1461 days
(end_2011 <- ymd("2011-12-31") - ymd(min(seg$date)))
## Time difference of 1825 days
Then look at power bands for periods 20-50 in 2011:
seg_2011_power <- as.matrix(seg_ta_avg.w_power[68:94, 1461:1825])
dimnames(seg_2011_power) <- list(paste0("period_", round(seg_ta_avg.w$Period[68:94], 2)))
seg_2011_power_t <- as_tibble(t(seg_2011_power))
seg_2011_power_df <- tibble(date = seq(from = ymd("2011-01-01"),
to = ymd("2011-12-31"),
by = "1 day"),
seg_2011_power_t)
seg_2011_power_df_long <- seg_2011_power_df %>%
pivot_longer(contains("period_"))
seg_2011_power_df_long %>%
ggplot(aes(x = date, y = value, color = name)) +
geom_line() +
facet_wrap(~ name) +
theme(legend.position="none") +
labs(title = "Average daily temperature in 2011",
x = "Date",
y = "Power") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
This first example was used to show a basic analytic process for analyzing wavelets and how to identify high power regions of interest in a univariate time series.
This synthetic example shows how wavelets can detect changes in periodicity throughout the time series (time-period domain). This is an advantage over other techniques that cannot detect non-stationarity.
This example comes directly from the guided tour.
First, produce synthetic/pretend data:
# made up data for example
x1 <- periodic.series(start.period = 100, length = 400)
x2 <- 1.5*periodic.series(start.period = 50, length = 200)
x <- c(x1, x2, x1) + 0.2*rnorm(1000)
pretend.data <- data.frame(x = x)
pretend.data %>%
ggplot(aes(x = seq(from = 1, to = 1000, by=1), y = x)) +
geom_line(size = 0.6, color = "tan") +
labs(title = "Non-Stationary Data Example",
x = "time",
y= "value")
Then conduct the wavelet transform and visualize:
pretend.w <- analyze.wavelet(pretend.data, "x",
method = "white.noise",
loess.span = 0,
dt = 1, dj = 1/250,
lowerPeriod = 32, upperPeriod = 256,
make.pval = TRUE, n.sim = 10)
## Starting wavelet transformation...
## ... and simulations...
##
|
| | 0%
|
|======= | 10%
|
|============== | 20%
|
|===================== | 30%
|
|============================ | 40%
|
|=================================== | 50%
|
|========================================== | 60%
|
|================================================= | 70%
|
|======================================================== | 80%
|
|=============================================================== | 90%
|
|======================================================================| 100%
## Class attributes are accessible through following names:
## series loess.span dt dj Wave Phase Ampl Power Power.avg Power.pval Power.avg.pval Ridge Period Scale nc nr coi.1 coi.2 axis.1 axis.2 date.format date.tz
wt.image(pretend.w, color.key = "interval", n.levels = 250,
legend.params = list(lab = "wavelet power levels"))
Notice how the wavelet image clearly identifies the changes in dominant periods throughout the time series.
Cross-wavelet analysis can be used to examing two time series variables at the same time to identify synchronicities and phase differences between the variables.
The two variables for this analysis are:
Before conducting the cross-wavelet analysis, let’s take look at the two variables by themselves.
seg %>%
ggplot(aes(x = date, y = P_int)) +
geom_line(size = 0.4, color = "tan") +
labs(title = "US-Seg - Daily Precipitation",
x = "Date",
y = "Precipitation (mm)")
seg %>%
ggplot(aes(x = date, y = NEE_int)) +
geom_line(size = 0.4, color = "tan") +
labs(title = "US-Seg - Net Ecosystem Exchange",
x = "Date",
y = "NEE (gC/m^2)")
And conduct univariate wavelet transforms:
seg_p_int.w <- analyze.wavelet(seg, "P_int",
loess.span = 0.75,
dt = 1, dj = 1/20,
make.pval = TRUE, method = "white.noise",
n.sim = 25)
## Smoothing the time series...
## Starting wavelet transformation...
## ... and simulations...
##
|
| | 0%
|
|=== | 4%
|
|====== | 8%
|
|======== | 12%
|
|=========== | 16%
|
|============== | 20%
|
|================= | 24%
|
|==================== | 28%
|
|====================== | 32%
|
|========================= | 36%
|
|============================ | 40%
|
|=============================== | 44%
|
|================================== | 48%
|
|==================================== | 52%
|
|======================================= | 56%
|
|========================================== | 60%
|
|============================================= | 64%
|
|================================================ | 68%
|
|================================================== | 72%
|
|===================================================== | 76%
|
|======================================================== | 80%
|
|=========================================================== | 84%
|
|============================================================== | 88%
|
|================================================================ | 92%
|
|=================================================================== | 96%
|
|======================================================================| 100%
## Class attributes are accessible through following names:
## series loess.span dt dj Wave Phase Ampl Power Power.avg Power.pval Power.avg.pval Ridge Period Scale nc nr coi.1 coi.2 axis.1 axis.2 date.format date.tz
mypalette <- "terrain.colors(100)"
wt.image(seg_p_int.w,
col.contour = "white",
color.palette = mypalette,
lwd = 1,
show.date = TRUE,
main = "US-Seg Flux Tower Daily Precipitation (mm)",
legend.params = list(width = 1.8, label.digits = 4))
seg_nee_int.w <- analyze.wavelet(seg, "NEE_int",
loess.span = 0.75,
dt = 1, dj = 1/20,
make.pval = TRUE, method = "white.noise",
n.sim = 100)
## Smoothing the time series...
## Starting wavelet transformation...
## ... and simulations...
##
|
| | 0%
|
|= | 1%
|
|= | 2%
|
|== | 3%
|
|=== | 4%
|
|==== | 5%
|
|==== | 6%
|
|===== | 7%
|
|====== | 8%
|
|====== | 9%
|
|======= | 10%
|
|======== | 11%
|
|======== | 12%
|
|========= | 13%
|
|========== | 14%
|
|========== | 15%
|
|=========== | 16%
|
|============ | 17%
|
|============= | 18%
|
|============= | 19%
|
|============== | 20%
|
|=============== | 21%
|
|=============== | 22%
|
|================ | 23%
|
|================= | 24%
|
|================== | 25%
|
|================== | 26%
|
|=================== | 27%
|
|==================== | 28%
|
|==================== | 29%
|
|===================== | 30%
|
|====================== | 31%
|
|====================== | 32%
|
|======================= | 33%
|
|======================== | 34%
|
|======================== | 35%
|
|========================= | 36%
|
|========================== | 37%
|
|=========================== | 38%
|
|=========================== | 39%
|
|============================ | 40%
|
|============================= | 41%
|
|============================= | 42%
|
|============================== | 43%
|
|=============================== | 44%
|
|================================ | 45%
|
|================================ | 46%
|
|================================= | 47%
|
|================================== | 48%
|
|================================== | 49%
|
|=================================== | 50%
|
|==================================== | 51%
|
|==================================== | 52%
|
|===================================== | 53%
|
|====================================== | 54%
|
|====================================== | 55%
|
|======================================= | 56%
|
|======================================== | 57%
|
|========================================= | 58%
|
|========================================= | 59%
|
|========================================== | 60%
|
|=========================================== | 61%
|
|=========================================== | 62%
|
|============================================ | 63%
|
|============================================= | 64%
|
|============================================== | 65%
|
|============================================== | 66%
|
|=============================================== | 67%
|
|================================================ | 68%
|
|================================================ | 69%
|
|================================================= | 70%
|
|================================================== | 71%
|
|================================================== | 72%
|
|=================================================== | 73%
|
|==================================================== | 74%
|
|==================================================== | 75%
|
|===================================================== | 76%
|
|====================================================== | 77%
|
|======================================================= | 78%
|
|======================================================= | 79%
|
|======================================================== | 80%
|
|========================================================= | 81%
|
|========================================================= | 82%
|
|========================================================== | 83%
|
|=========================================================== | 84%
|
|============================================================ | 85%
|
|============================================================ | 86%
|
|============================================================= | 87%
|
|============================================================== | 88%
|
|============================================================== | 89%
|
|=============================================================== | 90%
|
|================================================================ | 91%
|
|================================================================ | 92%
|
|================================================================= | 93%
|
|================================================================== | 94%
|
|================================================================== | 95%
|
|=================================================================== | 96%
|
|==================================================================== | 97%
|
|===================================================================== | 98%
|
|===================================================================== | 99%
|
|======================================================================| 100%
## Class attributes are accessible through following names:
## series loess.span dt dj Wave Phase Ampl Power Power.avg Power.pval Power.avg.pval Ridge Period Scale nc nr coi.1 coi.2 axis.1 axis.2 date.format date.tz
wt.image(seg_nee_int.w,
col.contour = "white",
color.palette = mypalette,
lwd = 1,
show.date = TRUE,
main = "US-Seg Flux Tower Net Ecosystem Exchange (gC/m^2)",
plot.ridge = FALSE,
legend.params = list(width = 1.8, label.digits = 4))
Now that we’ve looked at the two variables by themselves, it is time to conduct the cross-wavelet analysis of US-Seg precipitation and NEE:
seg_precip_nee <- seg %>%
select(date, P_int, NEE_int) %>%
as.data.frame()
seg_precip_nee.wc <- analyze.coherency(seg_precip_nee, my.pair = c("P_int", "NEE_int"),
loess.span = 0.75,
dt = 1, dj = 1/20,
make.pval = TRUE,
n.sim = 20)
## Smoothing the time series...
## Starting wavelet transformation and coherency computation...
## ... and simulations...
## Warning in sqrt(sPower.x * sPower.y): NaNs produced
##
|
| | 0%
|
|==== | 5%
|
|======= | 10%
|
|========== | 15%
|
|============== | 20%
|
|================== | 25%
|
|===================== | 30%
|
|======================== | 35%
|
|============================ | 40%
|
|================================ | 45%
|
|=================================== | 50%
|
|====================================== | 55%
|
|========================================== | 60%
|
|============================================== | 65%
|
|================================================= | 70%
|
|==================================================== | 75%
|
|======================================================== | 80%
|
|============================================================ | 85%
|
|=============================================================== | 90%
|
|================================================================== | 95%
|
|======================================================================| 100%
## Class attributes are accessible through following names:
## series loess.span dt dj Wave.xy Angle sWave.xy sAngle Power.xy Power.xy.avg Power.xy.pval Power.xy.avg.pval Coherency Coherence Coherence.avg Coherence.pval Coherence.avg.pval Wave.x Wave.y Phase.x Phase.y Ampl.x Ampl.y Power.x Power.y Power.x.avg Power.y.avg Power.x.pval Power.y.pval Power.x.avg.pval Power.y.avg.pval sPower.x sPower.y Ridge.xy Ridge.co Ridge.x Ridge.y Period Scale nc nr coi.1 coi.2 axis.1 axis.2 date.format date.tz
wc.image(seg_precip_nee.wc,
main = "Cross-wavelet power spectrum for\nUS-Seg Precipitation and NEE",
legend.params = list(lab = "cross-wavelet power levels"),
periodlab = "period (days)",
col.contour = "white",
color.palette = mypalette,
lwd = .8,
show.date = TRUE,
col.arrow = "red",
which.image = "wp"
)
The cross-wavelet power shows the similarity of the bivariate time series’ wavelet power in the time-frequency domain. Arrows to the right indicate when the two variables are in phase with one another, and arrows to the left indicate when the two variables are in anti-phase.
WaveletComp is a useful R package for conducting continuous wavelet-based analyses to identify periodicities in univariate or bivariate time series. Wavelets may be a useful tool for detecting transient high power pulses in a time series. There are many options available in WaveletComp for adjusting a wavelet analysis, and more detailed information can be found in the guided tour and package documentation.
The citation for the WaveletComp R package:
citation("WaveletComp")
##
## To cite package 'WaveletComp' in publications use:
##
## Angi Roesch and Harald Schmidbauer (2018). WaveletComp: Computational
## Wavelet Analysis. R package version 1.1.
## https://CRAN.R-project.org/package=WaveletComp
##
## A BibTeX entry for LaTeX users is
##
## @Manual{,
## title = {WaveletComp: Computational Wavelet Analysis},
## author = {Angi Roesch and Harald Schmidbauer},
## year = {2018},
## note = {R package version 1.1},
## url = {https://CRAN.R-project.org/package=WaveletComp},
## }
##
## ATTENTION: This citation information has been auto-generated from the
## package DESCRIPTION file and may need manual editing, see
## 'help("citation")'.